/*
 * Copyright (c) 2023-2024 HPMicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include <stdio.h>
#include <assert.h>
#include "board.h"
#include "hpm_mcan_drv.h"
#include "uart.h"
#include "spi.h"
#include "can.h"


/***********************************************************************************************************************
 *
 *  Prototypes
 *
 **********************************************************************************************************************/


void board_can_timeout_counter_test(void);

/**
 * @brief Display the CAN message content
 *
 * @param [in] rx_msg CAN message buffer
 */
void show_received_can_message(const mcan_rx_message_t *rx_msg);

/**
 * @brief CAN Interrupt Service Routine
 */
void board_can_isr(void);




/**
 * @brief Handler for CAN test options
 */
void handle_can_test(void);

/**
 * @brief Handle CAN errors
 */
void handle_can_error(MCAN_Type *ptr);

void show_help(void);

char *get_timestamp_hex_string(const mcan_timestamp_value_t *ts_val);


static volatile bool has_new_rcv_msg;

static volatile bool has_sent_out;

static volatile bool has_error;

static volatile bool tx_event_occurred;

static volatile bool timeout_event_occurred;

static volatile bool rxfifo0_event_occurred;

static volatile bool rxfifo1_event_occurred;

static volatile mcan_rx_message_t s_can_rx_buf;

static volatile mcan_tx_event_fifo_elem_t s_can_tx_evt;








/***********************************************************************************************************************
 *
 *  Codes
 *
 **********************************************************************************************************************/
uint8_t mcan_get_dlc_from_message_size(uint16_t size)
{
    if (size <= 8) return size;
    switch (size) {
        case 9: case 10: case 11: case 12: return 9;
        case 13: case 14: case 15: case 16: return 10;
        case 17: case 18: case 19: case 20: return 11;
        case 21: case 22: case 23: case 24: return 12;
        case 25: case 26: case 27: case 28: return 13;
        case 29: case 30: case 31: case 32: return 14;
        case 33 ... 48: return 15;
        default: return 16; // 49-64字节
    }
}






// 向指定CAN通道发送带ID的数据帧
hpm_stat_t send_data_to_can_with_id(const uint8_t *data, uint8_t length, uint16_t can_id, uint8_t channel, bool *ok)
{
    // 参数有效性检查：
    // 1. 数据指针不能为空
    // 2. 数据长度不能为0
    // 3. 数据长度不能超过CAN帧的最大长度（8字节）
    if (!data || length == 0 || length > 8) {
        *ok = false;  // 设置操作失败标志
        return status_invalid_argument;  // 返回无效参数错误
    };
    
    // 声明指向CAN控制器的指针
    MCAN_Type *can_base;
    
    // 根据通道号选择对应的CAN控制器基地址
    switch (channel) {
        case 1: 
            can_base = CAN_CHANNEL_1;  // 通道1对应的CAN控制器
            break;
        case 2: 
            can_base = CAN_CHANNEL_2;  // 通道2对应的CAN控制器
            break;
        case 3: 
            can_base = CAN_CHANNEL_3;  // 通道3对应的CAN控制器
            break;
        case 4: 
            can_base = CAN_CHANNEL_4;  // 通道4对应的CAN控制器
            break;
        default:
            *ok = false;  // 设置操作失败标志
            return status_invalid_argument;  // 返回无效参数错误（无效通道号）
    }

    // 创建CAN发送帧结构体
    mcan_tx_frame_t tx_frame;
    // 清零帧结构体，确保所有字段初始化为0
    memset(&tx_frame, 0, sizeof(mcan_tx_frame_t));
    
    // 设置CAN帧参数：
    tx_frame.std_id = can_id;      // 设置标准ID（11位标识符）
    tx_frame.dlc = length;         // 设置数据长度码（DLC），表示数据字节数
    tx_frame.rtr = 0;              // 设置为0表示数据帧（远程帧为1）
    
    // 复制用户数据到CAN帧的数据区域
    memcpy(tx_frame.data_8, data, length);
    
    // 使用阻塞方式发送CAN帧
    // 函数会等待直到帧成功发送或超时
    hpm_stat_t status = mcan_transmit_blocking(can_base, &tx_frame);

    // 设置操作成功标志（true=成功，false=失败）
    *ok = (status == status_success);
  
    // 返回发送操作的状态码
    return status;
}

//// 带ID参数的CAN发送函数（64字节分8帧发送）
//hpm_stat_t send_data_to_can_with_id(const uint8_t *data, uint8_t length, uint16_t can_id, uint8_t channel, bool *ok)
//{
//    if (!data || length == 0 || length > 8) {
    
//      *ok = false;
//      return status_invalid_argument;
    
//    };
//    MCAN_Type *can_base;
//    switch (channel) {
//      case  1:can_base = CAN_CHANNEL_1; break;
//      case  2:can_base = CAN_CHANNEL_2; break;
//      case  3:can_base = CAN_CHANNEL_3; break;
//      case  4:can_base = CAN_CHANNEL_4; break;
//      default:
//        *ok = false;
//        return status_invalid_argument;
//    }


//    mcan_tx_frame_t tx_frame;
//    memset(&tx_frame, 0, sizeof(mcan_tx_frame_t));
    
//    // 设置CAN帧参数
//    tx_frame.std_id = can_id;      // 使用传入的ID
//    tx_frame.dlc = length;         // 数据长度码
//    tx_frame.rtr = 0;              // 数据帧
    
//    // 复制数据到CAN帧
//    memcpy(tx_frame.data_8, data, length);
    
//    // 发送CAN帧
//    hpm_stat_t status = mcan_transmit_blocking(can_base, &tx_frame);

//    *ok = (status == status_success);
  
//    return status;

//}




hpm_stat_t send_data_to_canfd_with_id(const uint8_t *data, uint32_t length, uint32_t can_id, uint8_t channel, bool *ok)
{
    // 参数检查
    if (!data || length == 0 || length > 64) { // CANFD最大支持64字节
        *ok = false;
        return status_invalid_argument;
    }

    MCAN_Type *can_base;
    switch (channel) {
        case 1: can_base = CAN_CHANNEL_1; break;
        case 2: can_base = CAN_CHANNEL_2; break;
        case 3: can_base = CAN_CHANNEL_3; break;
        case 4: can_base = CAN_CHANNEL_4; break;
        default:
            *ok = false;
            return status_invalid_argument;
    }

    mcan_tx_frame_t tx_frame;
    memset(&tx_frame, 0, sizeof(tx_frame));
    
    // 设置CANFD帧参数
    tx_frame.std_id = can_id;      // 标准ID
    tx_frame.dlc = mcan_get_dlc_from_message_size(length); // 自动计算DLC
    tx_frame.rtr = 0;              // 数据帧
    tx_frame.canfd_frame = 1;      // 启用CANFD格式
    tx_frame.bitrate_switch = 1;   // 启用速率切换
    
    // 复制数据
    uint32_t msg_len = mcan_get_message_size_from_dlc(tx_frame.dlc);
    //memcpy(tx_frame.data_8, data, msg_len);
    memcpy(tx_frame.data_8, data, (msg_len < length) ? msg_len : length);

    // 阻塞式发送
    hpm_stat_t status = mcan_transmit_blocking(can_base, &tx_frame);
    *ok = (status == status_success);
    return status;
}

//// 修改后的发送函数（使用阻塞式API）
//hpm_stat_t send_data_to_canfd_with_id(const uint8_t *data, uint32_t length, 
//                                     uint32_t can_id, uint8_t channel, bool *ok)
//{
//    MCAN_Type *can_base;
//    switch (channel) {
//        case 1: can_base = CAN_CHANNEL_1; break;
//        case 2: can_base = CAN_CHANNEL_2; break;
//        case 3: can_base = CAN_CHANNEL_3; break;
//        case 4: can_base = CAN_CHANNEL_4; break;
//        default: *ok = false; return status_invalid_argument;
//    }

//    mcan_tx_frame_t tx_frame;
//    memset(&tx_frame, 0, sizeof(tx_frame));
//    tx_frame.std_id = can_id;
//    tx_frame.dlc = mcan_get_dlc_from_message_size(length);
//    tx_frame.rtr = 0;
    
//    #if USE_CANFD
//    tx_frame.canfd_frame = 1;
//    tx_frame.bitrate_switch = 1;
//    #endif
    
//    uint32_t msg_len = mcan_get_message_size_from_dlc(tx_frame.dlc);
//    memcpy(tx_frame.data_8, data, (msg_len < length) ? msg_len : length);
    
//    hpm_stat_t status = mcan_transmit_blocking(can_base, &tx_frame);
//    *ok = (status == status_success);
//    return status;
//}



//void process_can_data_to_spi(MCAN_Type *can_base, mcan_rx_message_t *rx_frame) 
//{
//    uint8_t channel = 0;
//    if (can_base == HPM_MCAN0) channel = 0;
//    else if (can_base == HPM_MCAN1) channel = 1;
//    else if (can_base == HPM_MCAN2) channel = 2;
//    else if (can_base == HPM_MCAN4) channel = 4;
//      ;

//    // 确保缓冲区有足够空间 (ID 2B + DLC 1B + 数据最多64B)
//    if (spi_tx_size + 3 + rx_frame->dlc > sizeof(spi_tx_buffer)) {
//        // 缓冲区满，直接发送现有数据
//        setup_spi_transfer(spi_tx_buffer, spi_tx_size);
//        spi_tx_size = 0;
//    }
    
//    // 构建SPI数据包：ID (2字节) + DLC (1字节) + 数据
//    spi_tx_buffer[spi_tx_size++] = (rx_frame->std_id >> 8) & 0xFF;
//    spi_tx_buffer[spi_tx_size++] = rx_frame->std_id & 0xFF;
//    spi_tx_buffer[spi_tx_size++] = rx_frame->dlc;
    
//    // 复制CAN数据到SPI缓冲区
//    for (int i = 0; i < rx_frame->dlc; i++) {
//        spi_tx_buffer[spi_tx_size++] = rx_frame->data_8[i];
//    }
    
//    // 立即发送（而不是等待缓冲区满）
//    setup_spi_transfer(spi_tx_buffer, spi_tx_size);
//}






/* 通用 CAN 中断处理函数 */
void mcan_isr_common(MCAN_Type *base, uint8_t channel)
{
    if (!mcan_get_interrupt_flags(base)) {
        return;  // 没有中断标志，直接返回
    }
    
    uint32_t flags = mcan_get_interrupt_flags(base);
    
    /* 处理RXFIFO0新消息 */
    if ((flags & MCAN_INT_RXFIFO0_NEW_MSG) != 0) {
        mcan_rx_message_t rx_buf;
        if (mcan_read_rxfifo(base, 0, &rx_buf) == status_success) {
            output_can_message(channel, rx_buf.std_id, rx_buf.dlc, rx_buf.data_8, "RXFIFO0");
            rxfifo0_event_occurred = true;
        }
    }
    
    /* 处理RXFIFO1新消息 */
    if ((flags & MCAN_INT_RXFIFO1_NEW_MSG) != 0) {
        mcan_rx_message_t rx_buf;
        if (mcan_read_rxfifo(base, 1, &rx_buf) == status_success) {
            output_can_message(channel, rx_buf.std_id, rx_buf.dlc, rx_buf.data_8, "RXFIFO1");
            rxfifo1_event_occurred = true;
        }
    }
    
    /* 处理RXBUF新消息 */
    if ((flags & MCAN_INT_MSG_STORE_TO_RXBUF) != 0) {
        for (uint32_t buf_idx = 0; buf_idx < MCAN_RXBUF_SIZE_CAN_DEFAULT; buf_idx++) {
            if (mcan_is_rxbuf_data_available(base, buf_idx)) {
                mcan_rx_message_t rx_buf;
                mcan_read_rxbuf(base, buf_idx, &rx_buf);
                mcan_clear_rxbuf_data_available_flag(base, buf_idx);
                output_can_message(channel, rx_buf.std_id, rx_buf.dlc, rx_buf.data_8, "RXBUF");
            }
        }
    }
    
    /* 处理TX事件 */
    if ((flags & MCAN_INT_TX_EVT_FIFO_NEW_ENTRY) != 0) {
        mcan_tx_event_fifo_elem_t tx_evt;
        mcan_read_tx_evt_fifo(base, &tx_evt);
        tx_event_occurred = true;
    }
    
    /* 处理传输完成事件 */
    if ((flags & MCAN_EVENT_TRANSMIT) != 0) {
        has_sent_out = true;
    }
    
    /* 处理错误事件 */
    if ((flags & MCAN_EVENT_ERROR) != 0) {
        has_error = true;
    }
    
    /* 处理超时事件 */
    if ((flags & MCAN_INT_TIMEOUT_OCCURRED) != 0) {
        timeout_event_occurred = true;
    }
    
    /* 清除已处理的中断标志 */
    mcan_clear_interrupt_flags(base, flags);
}

/* 各通道的中断服务函数 */
void board_can0_isr(void) { mcan_isr_common(HPM_MCAN0, 0); }
void board_can3_isr(void) { mcan_isr_common(HPM_MCAN3, 3); }
void board_can4_isr(void) { mcan_isr_common(HPM_MCAN4, 4); }
void board_can6_isr(void) { mcan_isr_common(HPM_MCAN6, 6); }

/* 声明中断服务函数 */
SDK_DECLARE_EXT_ISR_M(IRQn_MCAN0, board_can0_isr)
SDK_DECLARE_EXT_ISR_M(IRQn_MCAN3, board_can3_isr)
SDK_DECLARE_EXT_ISR_M(IRQn_MCAN4, board_can4_isr)
SDK_DECLARE_EXT_ISR_M(IRQn_MCAN6, board_can6_isr)